package com.example.immanager.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.immanager.common.Constants;
import com.example.immanager.entity.Permission;
import com.example.immanager.entity.Role;
import com.example.immanager.entity.RolePermission;
import com.example.immanager.entity.User;
import com.example.immanager.entity.domain.LoginDTO;
import com.example.immanager.entity.domain.UserRequest;
import com.example.immanager.exception.ServiceException;
import com.example.immanager.mapper.RolePermissionMapper;
import com.example.immanager.mapper.UserMapper;
import com.example.immanager.service.IPermissionService;
import com.example.immanager.service.IRoleService;
import com.example.immanager.service.UserService;
import com.example.immanager.utils.Md5Utils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @author Lukecheng
 * @date 2023/04/18
 */

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {


    @Resource
    IRoleService roleService;

    @Resource
    RolePermissionMapper rolePermissionMapper;

    @Resource
    IPermissionService permissionService;

    @Override
    public LoginDTO login(UserRequest user) {
        User dbUser;
        try {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getNickname,user.getNickname());
            dbUser = getOne(queryWrapper);
        } catch (Exception e) {
            throw new RuntimeException("数据库异常");
        }
        if (dbUser == null) {
            throw new ServiceException("未找到用户");
        }
        if(!Md5Utils.encrypt(user.getPassword()).equals(dbUser.getPassword())) throw new ServiceException("密码错误");
        if(dbUser.getIsActivated() == false){
            throw new ServiceException("你的账号未激活，请联系管理员激活");

        }
        StpUtil.login(dbUser.getId());  // loginId
        StpUtil.getSession().set(Constants.LOGIN_USER_KEY, dbUser);
        String tokenValue = StpUtil.getTokenInfo().getTokenValue();

        //查询用户的菜单树(2层)
        String flag = dbUser.getRole();  //用户角色
        List<Permission> all = getPermissions(flag);  // 水平
        List<Permission> menus = getTreePermissions(all); // 树
        // 页面的按钮权限集合
        List<Permission> auths = all.stream().filter(permission -> permission.getType() == 3).collect(Collectors.toList());
        return LoginDTO.builder().user(dbUser).token(tokenValue).menus(menus).auths(auths).build();
    }

    public List<Permission> getPermissions(String roleFlag) {
        Role role = roleService.getOne(new QueryWrapper<Role>().eq("flag", roleFlag));
        //获取该角色拥有的权限
        List<RolePermission> rolePermissions = rolePermissionMapper.selectList(new QueryWrapper<RolePermission>().eq("role_id", role.getId()));
        List<Integer> permissionIds = rolePermissions.stream().map(RolePermission::getPermissionId).collect(Collectors.toList()); //权限id
        List<Permission> permissionList = permissionService.list();
        List<Permission> all = new ArrayList<>();  // 水平的菜单树
        for (Integer permissionId : permissionIds) {
            permissionList.stream().filter(permission -> permission.getId().equals(permissionId)).findFirst()
                    .ifPresent(all::add);
        }
        return all;
    }

    // 获取角色对应的菜单树
    private List<Permission> getTreePermissions(List<Permission> all) {
        // 菜单树 1级 -> 2级
        List<Permission> parentList = all.stream().filter(permission -> permission.getType() == 1
                || (permission.getType() == 2 && permission.getPid() == null)).collect(Collectors.toList());// type==1 是目录  或者  pid = null
        for (Permission permission : parentList) {
            Integer pid = permission.getId();
            List<Permission> level2List = all.stream().filter(permission1 -> pid.equals(permission1.getPid())).collect(Collectors.toList());// 2级菜单
            permission.setChildren(level2List);
        }
        return parentList.stream().sorted(Comparator.comparing(Permission::getOrders)).collect(Collectors.toList());  // 排序
    }



    @Override
    public void logout(String uid) {
        // 退出登录
        StpUtil.logout(uid);
    }

    @Override
    public User saveUser(User user) {
        User dbUser = getOne(new UpdateWrapper<User>().eq("email", user.getEmail())
                .or().eq("nickname",user.getNickname())
        );
        if (dbUser != null) {
            throw new ServiceException("用户已存在");
        }
        if (StrUtil.isBlank(user.getPassword())) {
            user.setPassword( Md5Utils.encrypt("123"));   // 设置默认密码(加密)
        }
        //设置其余属性
        user.setGender(1);
        user.setAvatar("");
        user.setBirthday(user.getBirthday());
        user.setIsActivated(true);
        try {
            save(user);
        } catch (Exception e) {
            throw new RuntimeException("保存失败", e);
        }
        return user;
    }
}
